Skip to content

Add cross-language Split.serialize()#455

Open
XiaoHongbo-Hope wants to merge 1 commit into
apache:mainfrom
XiaoHongbo-Hope:split_optimize
Open

Add cross-language Split.serialize()#455
XiaoHongbo-Hope wants to merge 1 commit into
apache:mainfrom
XiaoHongbo-Hope:split_optimize

Conversation

@XiaoHongbo-Hope

@XiaoHongbo-Hope XiaoHongbo-Hope commented Jul 5, 2026

Copy link
Copy Markdown
Contributor

Purpose

Add Split.to_dict() to the Python bindings so a non-Rust reader (e.g. pypaimon) can rebuild its own split from a Rust-planned split and read the files directly — planning runs in Rust (the serial, driver-side bottleneck), reading stays in the existing reader, no re-planning.

Brief change log

PySplit::to_dict() exposes a planned split as a plain dict — bucket / paths / partition plus per-file metadata (file_path, schema_id, first_row_id, write_cols, …) and deletion files. Planning-only stats omitted.

Tests

test_split_to_dict_exposes_fields, test_split_to_dict_partition_and_reads.

API and Format

Additive — new Split.to_dict() Python method. No storage-format change.

Documentation

Covered by the method docstring.

@XiaoHongbo-Hope XiaoHongbo-Hope marked this pull request as draft July 5, 2026 03:11
@XiaoHongbo-Hope XiaoHongbo-Hope force-pushed the split_optimize branch 8 times, most recently from a1c8b00 to becb6aa Compare July 5, 2026 08:37
@XiaoHongbo-Hope XiaoHongbo-Hope marked this pull request as ready for review July 5, 2026 08:47
@JunRuiLee

Copy link
Copy Markdown
Contributor

Thanks @XiaoHongbo-Hope! A question on necessity first.

The direction of the read effort (#413) is to let pypaimon run its DataFrame read on the Rust core — initially as a basic, opt-in path behind a config flag, not a wholesale replacement, so it can mature alongside the pure-Python path. In that model Rust both plans and reads: PR3 already exposes new_read().read(splits) returning Arrow from the Rust TableRead, and splits stay opaque on the Python side — a transport token, nothing more — so pypaimon never needs to look inside one.

to_dict() exposes the full internal split contents, which is only needed if something rebuilds the split and reads the files outside Rust — i.e. reading in Python, which is the opposite of the direction #413 is moving in.

So: what's the use case for exposing split internals? If it's for a Rust-plans / Python-reads path, I think we should align on that direction first — otherwise it risks pulling us away from the opt-in Rust read path we're building toward.

@XiaoHongbo-Hope

Copy link
Copy Markdown
Contributor Author

Thanks @XiaoHongbo-Hope! A question on necessity first.

The direction of the read effort (#413) is to let pypaimon run its DataFrame read on the Rust core — initially as a basic, opt-in path behind a config flag, not a wholesale replacement, so it can mature alongside the pure-Python path. In that model Rust both plans and reads: PR3 already exposes new_read().read(splits) returning Arrow from the Rust TableRead, and splits stay opaque on the Python side — a transport token, nothing more — so pypaimon never needs to look inside one.

to_dict() exposes the full internal split contents, which is only needed if something rebuilds the split and reads the files outside Rust — i.e. reading in Python, which is the opposite of the direction #413 is moving in.

So: what's the use case for exposing split internals? If it's for a Rust-plans / Python-reads path, I think we should align on that direction first — otherwise it risks pulling us away from the opt-in Rust read path we're building toward.

Thanks, Junrui. Got your concern, will discuss with Jingsong and then back to you.

@XiaoHongbo-Hope

Copy link
Copy Markdown
Contributor Author

@JunRuiLee Thanks Junrui. My view: the read side can be handled by adding more workers in production, but plan runs on the driver. And It's additive and opt-in — no storage-format change — and it doesn't block #413; once full-Rust read lands, this just becomes an alternate/interim path.

@JingsongLi JingsongLi left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you need to use Python? Should we directly let AI see how to design cross language calls? For example, designing a cross language binary format for Split?

@JingsongLi

Copy link
Copy Markdown
Contributor

Let's create an unified protocol: apache/paimon#8482

@XiaoHongbo-Hope XiaoHongbo-Hope changed the title [python] Add Split.to_dict() to expose planned split contents Add cross-language Split.serialize() Jul 7, 2026
Comment thread crates/paimon/src/table/source.rs Outdated
/// v8 has no field for them, so silently dropping them would widen the split and read extra rows.
pub fn serialize(&self) -> crate::Result<Vec<u8>> {
if self.row_ranges.is_some() {
return Err(crate::Error::DataInvalid {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe it is the time to create IndexedSplit.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe it is the time to create IndexedSplit.

Done.

@XiaoHongbo-Hope XiaoHongbo-Hope force-pushed the split_optimize branch 2 times, most recently from 22a835c to ab7dd39 Compare July 8, 2026 03:39
Expose a planned split as the standard Java SplitSerializer (v1) binary so any Paimon reader (pypaimon, Java) can rebuild it without re-planning, replacing the earlier Python-only to_dict(). A plain split serializes as DataSplit (v8); a split carrying row ranges as IndexedSplit (type 3).

Not a new format: byte-for-byte verified against Java's compatibility/datasplit-v8, split-v1-data and split-v1-indexed goldens (added as Rust tests). writeUTF is faithful Java modified UTF-8 with a length check.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants